import type { PluginOption } from 'vite'

export default function dome(): PluginOption {
    return {
        // TODO 书写一个插件时 插件名必填
        name: 'vite-plugin-test',
        // TODO enforce: 通过该属性来调整插件加载顺序，可选值：pre（前置） | post（后置）
        // TODO `enforce: 'pre'`表示规则将在代码被解析/分析之前执行，而`enforce: 'post'`表示规则将在代码被解析/分析之后执行
        enforce: 'post',
        // TODO 默认情况下插件在开发（serve）和构建（build）模式中都会调用。如果插件只需要在预览或构建期间有条件地应用，请使用 apply 属性指明它们仅在 'build' 或 'serve' 模式时调用：
        apply: 'serve',
        // TODO 在解析 Vite 配置前调用。钩子接收原始用户配置, 可以返回用来改变默认的部分配置
        config: (config, env) => {
            // console.log(config, env, '>>>>>>')
            console.log('1')
            return {
                ...config,
                resolve: {
                    alias: {
                        foo: 'bar',
                    },
                },
            }
        },
        // TODO 无返回值，可以用来存储 最终解析的配置，当插件需要根据运行的命令做一些不同的事情时，它也很有用
        configResolved(config) {
            // config.resolve.alias.map((item) => {
            //     console.log(item, '>>>>>>>>>')
            // })
            console.log('2')
        },
        // TODO 在服务器启动时被调用：获取、操纵Rollup选项，严格意义上来讲，它执行于属于构建阶段之前；
        options: (options) => {
            // (options: InputOptions) => InputOptions | null
            console.log('3')

            // return {
            //     ...options,
            //     input: ''
            // }
            // return options
        },
        // TODO 是用于配置开发服务器的钩子。最常见的用例是在内部 connect 应用程序中添加自定义中间件:
        configureServer(server) {
            // server.middlewares.use((req, res, next) => {
            //     next()
            // })
            console.log('4')
        },
        // TODO 在 rollup 构建中，vite （本地）服务启动时调用，在这个函数中可以访问 rollup 的配置
        buildStart(options) {
            // console.log(options)
            console.log('5')
        },
        // TODO 在每个传入模块请求时被调用，创建自定义确认函数，可以用来定位第三方依赖；
        // TODO 在项目打开后，会进入这里进行，构建
        resolveId(source, importer, options) {
            // console.log(source, '得到请求的资源相对路径')
            // console.log(importer, '得到index.html 的绝对地址')
            // console.log(options, '得到一个配置options')
            // console.log('>>>>>>>>>>>')
            console.log('6')
        },
        // TODO 在每个传入模块请求时被调用，可以自定义加载器，可用来返回自定义的内容；
        // TODO 每次resolveId 完成都会触发这里的load
        load(id, options) {
            // console.log(id, '得到读取文件的绝对路径地址')
            // console.log(options, '只有一个属性 ssr')
            console.log('7')
        },
        transform(code, id, options) {
            // console.log(code, '拿到代码的字符串表现形式')
            // console.log(id, '拿到请求当前文件的绝对路径')
            // console.log(options, '只有一个属性 ssr')
            console.log('8')
        },
        // TODO 在构建阶段结束后被调用，此处构建结束只是代表所有模块转义完成；
        // TODO 每次构建结束后，又会重新 构建
        buildEnd(error) {
            // console.log('>>>>>>>>>>>buildEnd')
            // console.log(error)
            // console.log('8')
            console.log(`Build duration: ${error.message}ms`)
            console.log(`Warnings: ${error.name}`)
            console.log(`Errors: ${error.stack}`)
            console.log('9')
        },

        // 输出阶段通用钩子
        // TODO build 阶段
        outputOptions(options) {
            // console.log(options, '打包的信息')
            console.log('10')
        },
        renderStart(options) {
            // console.log(this, '插件上下文')
            // console.log(options, '更加全面的一些build信息')
            console.log('11')
        },
        augmentChunkHash(chunk) {
            // console.log(chunk, '收集到打包的chunk')
            console.log('12')
        },
        renderChunk(code, chunk, options, meta) {
            console.log('13')
        },
        generateBundle(options, bundle, isWrite) {
            // console.log('生成 Bundle')
            console.log('14')
        },
        transformIndexHtml() {
            console.log('15')
        },
        writeBundle(options, bundle) {
            // console.log('写入 bundle')
            console.log('16')
        },
        closeBundle() {
            // console.log('关闭bundle 写入')
            console.log('17')
        },
        closeWatcher() {
            console.log('closeWatcher')
        },
    }
}

// TODO 每一个钩子中都注入了插件上下文

// TODO 如果项目没有打开，会默认触发  1 2 3 4 5
// TODO 如果项目没有打开, 但是按了 Ctrl + S, 是第二次构建 1 2 3 4 9 5
// TODO 当项目在浏览器打开 1 2 3 4 9 5 后面将会是一个 6 7 8 这里将处理请求的资源

// TODO 如果是build 模式下 会触发 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 (按照流程全部触发一次)
